import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from "axios";
import { getCancelToken, waitResendCanceledRequest } from "./cancel";
import { requestCommonParams } from "./config";
import { requestLog, Message } from "./tools";
import { userModule } from '@/store/modules/user'
import Qs from "qs";
// eslint-disable-next-line
import MD5 from "js-md5";
import {
  REPEAT_URL_WHITES
} from "./config";
import router from "@/core/router";

export enum HTTP_CODE {
  SUCCESS = 200,
  UNAUTHORIZED = 401,
  NOT_FOUND = 404,
  SERVICE_ERROR = 500,
}

export enum BUSINESS_CODE {
  SUCCESS = 200,
  UNAUTHORIZED = 405,
  ERROR = 500
}

export enum BUSINESS_FIELD {
  CODE = "code",
  MESSAGE = "msg"
}

/**
 * 请求成功拦截器
 *
 * @export
 * @param {AxiosRequestConfig} config
 * @return {*}  {AxiosRequestConfig}
 */
export function requestInterceptorsSuccess(config: AxiosRequestConfig): AxiosRequestConfig {
  console.log("config:", config);
  requestLog(config);
  return config;
}

/**
 * 请求失败拦截器
 *
 * @export
 * @param {AxiosRequestConfig} config
 * @return {*}  {Promise<AxiosRequestConfig>}
 */
export function requestInterceptorsFail<T extends AxiosError<Api.ResponseOptions>>(error: T): Promise<T> {
  console.error("请求失败", error);
  return Promise.reject(error);
}

/**
 * 响应异常
 *
 * @export
 * @param {AxiosResponse<Api.ResponseOptions>} response
 * @return {*}
 */
export function responseInterceptorsFail(error: AxiosError<Api.ResponseOptions>): Promise<AxiosResponse<Api.ResponseOptions>> {
  console.error("响应失败", error);
  // 请求取消
  if (axios.isCancel(error)) {
    return waitResendCanceledRequest(error.message);
  }
  const { response, message } = error;
  // 网络异常
  if (message === "Network Error") {
    // @ts-ignore
    releaseHash({
      config: error.config
    });
    Message.fail("网络异常");
    return Promise.reject(error);
  }
  // 请求重复
  if (message === '请求重复') {
    // @ts-ignore
    releaseHash({
      config: error.config
    });
    return Promise.reject(error);
  }
  // @ts-ignore
  releaseHash(response)
  
  switch (response && response.status) {
    case HTTP_CODE.UNAUTHORIZED:
      localStorage.removeItem("token");
      Message.fail(response && response.data[BUSINESS_FIELD.MESSAGE]);
      router.push('/login');
      break;
    case HTTP_CODE.SERVICE_ERROR:
      Message.fail("数据异常！！");
      break;
  }
  return Promise.reject(response);
}

/**
 * 响应成功
 *
 * @export
 * @param {AxiosResponse} response
 * @return {*}  {AxiosResponse}
 */
export function responseInterceptorsSuccess<T extends AxiosResponse<Api.ResponseOptions>>(response: T): T | Promise<T> {
  return response.status === HTTP_CODE.SUCCESS ? response : Promise.reject(response);
}

/**
 * 业务相关相应拦截
 *
 * @export
 * @template T
 * @param {T} data
 * @return {*}  {(T | Promise<T>)}
 */
export function businessResponse<T extends AxiosResponse<A>, A extends Api.ResponseOptions>(response: T) {
  const {
    data,
    config
  } = response;
  // 自定义处理业务逻辑
  if (config?.customHandler) {
    console.log("customHandler-businessResponse", config.customHandler, response);
    return response;
  }

  console.log(response)

  switch (data[BUSINESS_FIELD.CODE]) {
    case BUSINESS_CODE.SUCCESS:
      console.log("businessResponse", data);
      return data;
    case BUSINESS_CODE.UNAUTHORIZED:
      sessionStorage.removeItem("token");
      Message.fail(data[BUSINESS_FIELD.MESSAGE]);
      // router.push('/login');
      // sessionStorage.getItem("logout") && (location.href = sessionStorage.getItem("logout"));
      throw data;
    default:

      Message.fail(data[BUSINESS_FIELD.MESSAGE]);
      throw data;
  }
}

/**
 * 注入公共参数
 *
 * @export
 * @param {AxiosRequestConfig} config
 * @return {*}  {AxiosRequestConfig}
 */
export function injectCommonParams(config: AxiosRequestConfig): AxiosRequestConfig {
  // 忽略公共参数
  if (config.ignoreCommonParams) {
    return config;
  }
  // 动态加载
  let _requestCommonParams: Record<string, string> = {
    ...requestCommonParams,
    task_id: userModule.currentProject.task_id || '',
    year:  '' + userModule.currentYear || ''
  }
  const METHOD = config.method ?.toLocaleUpperCase();
  switch (METHOD) {
    case "GET":
      config.params = Object.assign(_requestCommonParams, config.params || {});
      break;
    default:
      if (config.data instanceof FormData) {
        for (const key in _requestCommonParams) {
          config.data.append(key, _requestCommonParams[key]);
        }
      } else {
        config.data = Object.assign(_requestCommonParams, config.data || {});
      }
  }
  return config;
}



/**
 * 切换参数格式
 *
 * @export
 * @param {AxiosRequestConfig} config
 * @return {*}  {AxiosRequestConfig}
 */
export function injectSwitchContentType(config: AxiosRequestConfig): AxiosRequestConfig {
  // 默认json格式
  if (typeof config.isJSON === "undefined") {
    config.isJSON = true;
  }
  // form-data格式化数据
  if (!config.isJSON) {
    config.data = Qs.stringify(config.data);
  }
  return config;
}

/**
 * 注入自定义参数
 *
 * @export
 * @param {AxiosRequestConfig} config
 * @return {*}  {AxiosRequestConfig}
 */
export function injectCustomParams(config: AxiosRequestConfig): AxiosRequestConfig {
  // isHorizontalScreen
  return config;
}

/**
 * 注入头部信息
 *
 * @export
 * @param {AxiosRequestConfig} config
 * @return {*}  {AxiosRequestConfig}
 */
export function injectHeader(config: AxiosRequestConfig): AxiosRequestConfig {
  const token = sessionStorage.getItem("token");
  const token2 = sessionStorage.getItem("token2");
  const sign = MD5(`${token2}lhhsm-66xxgmgt${JSON.stringify(config.data || [])}`)
  const header = {
    lhhsm: `${token}_${sign}`
  };
  config.headers = Object.assign(config.headers, header);
  return config;
}

// 当前请求接口队列
export const currentRequestQueue: string[] = [];
/**
 * 校验当前请求是否正在进行
 *
 * @export
 * @param {AxiosRequestConfig} config
 * @return {*}
 */
export async function injectHash(config: AxiosRequestConfig) {
  if (config._hash) return config;
  // 白名单
  if (config.url && REPEAT_URL_WHITES.includes(config.url)) return config;
  const hash = generateApiHash(config);
  if (currentRequestQueue.includes(hash)) {
    // throw "请求重复";
    return Promise.reject({
      message: "请求重复",
      config
    })
  }
  config._hash = hash;
  config.cancelToken = getCancelToken(hash, config);
  currentRequestQueue.push(hash);
  return config;
}

/**
 * 释放请求hash
 *
 * @export
 * @param {AxiosResponse} response
 * @return {*}
 */
export async function releaseHash(response: AxiosResponse) {
  if (!response) return response;
  const hash = response.config ?._hash;
  const hashIndex = hash ? currentRequestQueue.indexOf(hash) : -1;
  if (hashIndex !== -1) {
    currentRequestQueue.splice(hashIndex, 1);
  }
  console.info("requestQueue =>", currentRequestQueue);
  return response;
}

/**
 * 生成请求hash
 *
 * @export
 * @param {AxiosRequestConfig} config
 * @return {*}
 */
export function generateApiHash(config: AxiosRequestConfig) {
  const data = config.method ?.toUpperCase() === "GET" ? config.params : config.data;
  return MD5(config.url + (typeof data === "string" ? data : JSON.stringify(data || {}))).toString();
}
